package fons.navigator.views.island.maps;

import java.awt.Color;
import java.util.List;

import com.google.common.collect.Lists;

import fons.model.ontology.ValueSpace;
import fons.navigator.views.island.ColorField;
import fons.navigator.views.island.Island;
import fons.navigator.views.island.MapColorManager;
import fons.navigator.views.island.MapGrid;
import fons.navigator.views.island.VisualIsland;

public class ForceColorField implements ColorField {
	private final VisualIsland visualIsland;
		
	public VisualIsland getVisualIsland() {
		return visualIsland;
	}
	
	private class Source {
		public final double x, y;
		public final float r, g, b;
		public Source (double x, double y, float r, float g, float b) {
			this.x = x; this.y = y; this.r = r; this.g = g; this.b = b;
		}
	}
	
	private final List<Source> sources;
	
	public ForceColorField (VisualIsland visualIsland) {
		this.visualIsland = visualIsland;
		this.sources = Lists.newArrayListWithCapacity(getVisualIsland().getIslands().size());
		
		final MapColorManager colors = getVisualIsland().getColorManager();
		final double scale = getVisualIsland().getValueScale();
		
		for (Island island: getVisualIsland().getIslands()) {
			float r = 0, g = 0, b = 0;
			for (ValueSpace vsp: getVisualIsland().getValueSpaces()) {
				r += colors.redOf(vsp, (float) island.getValueOf(vsp));
				g += colors.greenOf(vsp, (float) island.getValueOf(vsp));
				b += colors.blueOf(vsp, (float) island.getValueOf(vsp));
			}
			r /= 2; g /= 2; b /= 2; 
			sources.add(new Source(island.getXOffset()*scale, island.getYOffset()*scale, r, g, b));
		}
	}
	
	public void add (double x, double y, float r, float g, float b) {
		this.sources.add(new Source(x, y, r, g, b));
	}
	
	@Override
	public Color at(double x, double y, MapGrid.MapQuad quad) {
		float r = 0, g = 0, b = 0;
		for (Source source: sources) {
			final double dx = x - source.x;
			final double dy = y - source.y;
			final double d = 1 - Math.tanh((dx*dx + dy*dy) * sources.size() * getVisualIsland().getColorIntensity());
			r += source.r * d;
			g += source.g * d;
			b += source.b * d;
		}
		return new Color(r > 1 ? 1 : r, g > 1 ? 1 : g, b > 1 ? 1 : b);
	}
}